# -*- coding: utf-8 -*
import re
import subprocess

from ..common import Collector
from easydict import EasyDict as edict
from typing import Dict, List, Tuple


class MemMetricCollector(Collector):
    """内存性能数据收集器：空闲区内存占总内存比例、交换区空闲比例、缓存和缓冲区比例"""
    def __init__(self, is_test):
        super().__init__(is_test)
        self.metrics_dict = edict({
            "Mem": {
                "total": 0.0,  # 单位统一转换成Mi
                "used": 0.0,
                "free": 0.0,
                "shared": 0.0,
                "buff_cache": 0.0,
                "available": 0.0
            },
            "Swap": {
                "total": 0.0,
                "used": 0.0,
                "free": 0.0
            }
        })

    def get_metric(self, metric: str) -> Dict[str, float]:
        return self.metrics[metric]

    def collect(self) -> Tuple[float, float, float]:
        mem_metric_pat = re.compile(r"(\d+|\d+\.\d+)(Mi|Gi)")
        if self.is_test:
            test_file_path = Collector.get_test_file_path("free.txt", __file__)
            with open(test_file_path, "r", encoding="utf-8") as f:
                lines = f.readlines()
                lines = lines[1:]
            out_str = "".join(lines)
        else:
            process_out = subprocess.run(["free", "-h", "1", "1"], stdout=subprocess.PIPE, stderr=subprocess.PIPE)
            out_str = str(process_out.stdout, encoding="utf-8")

        mem_metrics: List[Tuple[str, str]] = mem_metric_pat.findall(out_str)
        dict_keys = ["total", "used", "free", "shared", "buff_cache", "available"]
        for i in range(len(mem_metrics)):
            idx = i if i < 6 else i - 6
            dict_key = dict_keys[idx]
            metric_val = float(mem_metrics[i][0])
            if mem_metrics[i][1] == "Gi":
                metric_val = metric_val * 1024
            if i < 6:
                self.metrics_dict.Mem[dict_key] = metric_val
            else:
                self.metrics_dict.Swap[dict_key] = metric_val

        self.stash.append(self.metrics_dict.Mem.free / self.metrics_dict.Mem.total)
        self.stash.append(self.metrics_dict.Swap.free / self.metrics_dict.Swap.total)
        self.stash.append(self.metrics_dict.Mem.buff_cache / self.metrics_dict.Mem.total)
        return (self.metrics_dict.Mem.free / self.metrics_dict.Mem.total,
                self.metrics_dict.Swap.free / self.metrics_dict.Swap.total,
                self.metrics_dict.Mem.buff_cache / self.metrics_dict.Mem.total)
